﻿
this.trilhaImovel = (function () {
    return {};
}());

this.trilhaImovel.config = (function () {

    var myDomain = location.protocol + '//' +
                   location.hostname + ':' +
                   location.port;

    return {
        MAP_PAGE: "/Map/ViewProperties/",
        LOG_GEOCODING_USE: myDomain + "/Home/RegisterGeocodingUse",
        CHECK_GEOCODING_USE: myDomain + "/Home/IsAllowedGeocodingUse",
        GET_MARKERS_AS_ESTATE: myDomain + "/Map/GetRentMarkersAsync",
        GET_INTERESTING_MARKERS: myDomain + "/Map/GetInterestPointsAsync",
        VIEW_ESTATE_DETAIL: myDomain + "/Estate/ViewDetail/",
        MAP_CONTAINER_ID: "mapContainer",
        SEARCH_FORM: "searchForm",
        SEARCH_BTN_CONTROL: "btnSearch",
        SEARCH_TXT_CONTROL: "txtSearch",
        MAP_ZOOM_DEFAULT: 15,
        HIDDEN_LAT_ID: "initialPoint_Lat",
        HIDDEN_LNG_ID: "initialPoint_Lng",
        SLIDER_DISTANCE_ID: "sldDistanceKm",
        ESTATE_LIST_ID: "estateListView",
        mapCenterPoint: {
            lat: -23.49106,
            lng: -47.45010
        },
        HEADING: {
            NORT: 0,
            EAST: 90,
            SOUTH: 180,
            WEST: 270
        },
        CREATE_CIRCLE_AROUND_INITIAL_MARKER: true
    };

} ());

this.trilhaImovel.config.msg = (function () {

    return {
        MAP_CONTAINER_NOT_FOUND: "O elemento que deve receber o mapa não foi encontrado.",
        LOCATION_NOT_FOUND: "O endereço pesquisado não foi localizado.",
        TOO_MANY_LOCATION: "O endereço pesquisado retornou mais de uma localização.",
        GEOCODING_CONTROL_FAIL: "Os controles que participam do geocoding não foram encontrados.",
        GEOCODING_INVALID_TEXT_SEARCH: "Informe um endereço válido para a localização.",
        GEOCODING_LIMIT_ACHIEVED: "Limite de uso atingido.",
        MAP_NOT_INITIALIZED: "Não é possível adicionar ponto inicial porque o mapa não foi iniciado.",
        INITIAL_POINT_TITLE: "Você está aqui!",
        INFORMATION_TITLE: "Informação",
        ERROR_TITLE: "Erro"
    };

}());

this.trilhaImovel.config.img = (function () {

    return {
        MAP_ICONS_PATH: "/Content/MapIcons/", // Path to directory that stores icons map

        iconsData: { // Collection of data to extract icon from sprite

            Estate: {id: "Estate", icon: "home.png"},

            Hospital: {id: "Hospital", icon: "hospital.png"},
            Info: {id: "Info", icon: "info.png"},
            Police: {id: "Police", icon: "police2.png"},
            School: {id: "School", icon: "school.png"},
            ShoppingCenter: {id: "ShoppingCenter", icon: "shoppingmall.png"},
            Square: {id: "Square", icon: "park-urban.png"},
            Stadium: {id: "Stadium", icon: "stadium.png"},
            Supermarket: {id: "Supermarket", icon: "supermarket.png"}

        }
    };

} ());

this.trilhaImovel.consumer = (function (cfg) {

    var defaultCallbackError = (function (xhr, ajaxOptions, thrownError) {
        window.alert("Erro: " + xhr.status + "\n" + thrownError);
        //window.alert(thrownError);
    });

    var emptyCallbackError = (function (xhr, ajaxOptions, thrownError) { });

    var request = (function (backEndMethod, callbackSuccess, callbackError) {

        if (typeof callbackSuccess === "function") {
            if (callbackError === null) {
                callbackError = defaultCallbackError;
            }

            $.ajax({
                type: "POST",
                url: backEndMethod,
                dataType: "json",
                success: callbackSuccess,
                error: defaultCallbackError
            });
        }
    });

    var requestWithData = function (backEndMethod, methodData, callbackSuccess, callbackError) {

        if (typeof callbackSuccess === "function") {
            if (callbackError === null) {
                callbackError = defaultCallbackError;
            }

            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: backEndMethod,
                dataType: "json",
                data: methodData,
                success: callbackSuccess,
                error: defaultCallbackError
            });
        }
    };

    return {
        doRequest: request,
        doRequestWithData: requestWithData
    };

} (trilhaImovel.config));

this.trilhaImovel.maps = (function (consumer, cfg, img, msg) {

    var MAP_DONE_EVENT = "MapDoneEvent",
        INITIAL_POINT_LOCATED = "InitialPointLocatedEvent",
        RENT_POINTS_ADDED_EVENT = "RentPointsAddedEvent",
        INTERESTING_POINTS_ADDED_EVENT = "InterestingPointsAddedEvent";

    var imageIcons = [], // Variable that stores icons used to identify places at map.
        map,
        geocoder,
        initialPoint,
        bounds,
        infoWindowDetail,
        boundSquareAroundCenter,
        distanceBounds,
        markersShowing;

    /*
    * Load all icons that will be used to identify places at map.
    */
    var loadImages = (function () {

        var imgMarker;

        for (imgMarker in img.iconsData) {
            if (img.iconsData.hasOwnProperty(imgMarker)) {
                imageIcons[img.iconsData[imgMarker].id] = new google.maps.MarkerImage(
                    img.MAP_ICONS_PATH + img.iconsData[imgMarker].icon,
                    null,
                    null,
                    null
                );
            }
        }
    });

    var initializeVariables = (function () {
        bounds = new google.maps.LatLngBounds();
        infoWindowDetail = new google.maps.InfoWindow({ content: "" });
        loadImages();
        markersShowing = [];
    });

    var createNewMap = (function () {

        var mapContainer = this.document.getElementById(cfg.MAP_CONTAINER_ID);

        if (mapContainer) {

            // Creating a new map
            var options = {
                zoom: cfg.MAP_ZOOM_DEFAULT,
                center: new google.maps.LatLng(cfg.mapCenterPoint.lat, cfg.mapCenterPoint.lng),
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            map = new google.maps.Map(this.document.getElementById(cfg.MAP_CONTAINER_ID), options);

        } else {
            window.alert(msg.MAP_CONTAINER_NOT_FOUND);
        }
    });

    var showBoundsApplyingDistance = (function (initialPoint, distanceInMeters, heading) {

        var originPoint = new google.maps.LatLng(initialPoint.lat(), initialPoint.lng());
        var pointFounded = google.maps.geometry.spherical.computeOffset(originPoint, distanceInMeters, heading);

        return pointFounded;
    });

    var getBoundsToReceiveMarkers = (function (initialPoint, distanceInMeters) {

        var eastPoint = showBoundsApplyingDistance(initialPoint, distanceInMeters, cfg.HEADING.EAST);
        var southeast = showBoundsApplyingDistance(eastPoint, distanceInMeters, cfg.HEADING.SOUTH);

        var westPoint = showBoundsApplyingDistance(initialPoint, distanceInMeters, cfg.HEADING.WEST);
        var nortwest = showBoundsApplyingDistance(westPoint, distanceInMeters, cfg.HEADING.NORT);

        boundSquareAroundCenter = {
            nortwestPoint: { lat: nortwest.lat(), lng: nortwest.lng() },
            southeastPoint: { lat: southeast.lat(), lng: southeast.lng() }
        };

    });

    var addInitialPointToMap = (function (latitude, longitude) {

        if (map) {

            var distanceInMeters = getFilterDistanceInMeters();
            var newLatLng = new google.maps.LatLng(latitude, longitude);

            // Center the map on the returned location
            map.setCenter(newLatLng);

            // Check to see if we've already got a Marker object
            if (!initialPoint) {
                // Creating a new marker and adding it to the map
                initialPoint = new google.maps.Marker({
                    map: map,
                    draggable: true,
                    title: msg.INITIAL_POINT_TITLE
                });

                // Add dragging event listeners.
                google.maps.event.addListener(initialPoint, 'dragstart', function () {
                    // Implementation...
                });

                google.maps.event.addListener(initialPoint, 'drag', function () {
                    // Implementation...
                });

                google.maps.event.addListener(initialPoint, 'dragend', function () {
                    var distanceInMeters = getFilterDistanceInMeters();
                    getBoundsToReceiveMarkers(this.getPosition(), distanceInMeters);
                    addDistanceBounds();
                    map.panTo(this.getPosition());
                    addRentPoints(distanceInMeters);
                });

                getBoundsToReceiveMarkers(newLatLng, distanceInMeters);
            }

            // Setting the position of the marker to the returned location
            initialPoint.setPosition(newLatLng);
            //bounds.extend(newLatLng);

        } else {
            window.alert(msg.MAP_NOT_INITIALIZED);
        }
    });

    var addDistanceBounds = (function () {

        if (distanceBounds) {
            distanceBounds.setMap(null);
        }

        if (initialPoint && cfg.CREATE_CIRCLE_AROUND_INITIAL_MARKER) {

            var point1 = new google.maps.LatLng(boundSquareAroundCenter.nortwestPoint.lat, boundSquareAroundCenter.nortwestPoint.lng);
            var point2 = new google.maps.LatLng(boundSquareAroundCenter.nortwestPoint.lat, boundSquareAroundCenter.southeastPoint.lng);
            var point3 = new google.maps.LatLng(boundSquareAroundCenter.southeastPoint.lat, boundSquareAroundCenter.southeastPoint.lng);
            var point4 = new google.maps.LatLng(boundSquareAroundCenter.southeastPoint.lat, boundSquareAroundCenter.nortwestPoint.lng);

            var polygonOptions = {
                paths: [point1, point2, point3, point4],
                clickable: false,
                map: map,
                strokeWeight: 1,
                strokeOpacity: 0.6,
                fillOpacity: 0.1
            };

            distanceBounds = new google.maps.Polygon(polygonOptions);
        }
    });

    var showDetailAboutEstate = (function (e) {
        alert('teste');
    });

    var closeInfoWindow = (function () {
        if (infoWindowDetail) {
            infoWindowDetail.close();
        }
    });

    var addBallonHandlers = (function (itemId) {

        setInterval(function () {

            $("#LnkSeeAtList_" + itemId).bind('click', function (event) {
                var Y_Point = $("#List_" + itemId.toString()).offset().top;
                $.mobile.silentScroll(Y_Point);
                event.preventDefault();
            });

            //            $("#LnkSeeDetail_" + itemId).bind('click', function (event) {
            //                alert(itemId);
            //                event.preventDefault();
            //            });

        }, 200);

    });

    var addRentPoints = (function (distanceTarget) {

        var methodData = {
            LatLeft: boundSquareAroundCenter.nortwestPoint.lat,
            LngLeft: boundSquareAroundCenter.nortwestPoint.lng,
            LatRight: boundSquareAroundCenter.southeastPoint.lat,
            LngRight: boundSquareAroundCenter.southeastPoint.lng
        };

        clearMarkers();

        var bounds1 = new google.maps.LatLngBounds();

        if (initialPoint) {
            bounds1.extend(initialPoint.getPosition());
        }

        addDistanceBounds();

        consumer.doRequestWithData(cfg.GET_MARKERS_AS_ESTATE, JSON.stringify(methodData), function (data) {

            var i = 0,
                markerListener,
                isMarkerAllowed;

            markerListener = function () {

                infoWindowDetail.setContent(this.html);
                infoWindowDetail.open(map, this);

                var itemId = this.dataSource.Id;
                addBallonHandlers(itemId);

            };

            for (; i < data.length; i++) {

                var point = new google.maps.LatLng(data[i].PointLocation.Latitude, data[i].PointLocation.Longitude);

                bounds1.extend(point);

                var markerRent = new google.maps.Marker({
                    position: point,
                    map: map,
                    icon: imageIcons[data[i].MarkerType],
                    html: createInfoWindowHTML(data[i])
                });

                markerRent.dataSource = data[i];
                google.maps.event.addListener(markerRent, "click", markerListener);

                markersShowing.push(markerRent);
            }

            bindEstateToList();

            if (markersShowing.length > 0) {
                map.fitBounds(bounds1);
            }

            $(window).trigger({
                type: RENT_POINTS_ADDED_EVENT
            });
        },
            null
        );

    });

    var createInfoWindowHTML = (function (data) {

        var html = "<p>" + data.OperationType + " - " + data.PropertyType + "<br />" +
                   "Valor: R$ " + data.PriceOrRentValue + "</p>" +
                   "<p>" + data.Address.Street + "<br />" +
                   data.Address.Neighborhood + " - " + data.Address.City + ", " + data.Address.State + "</p>" +
                   "<a id='LnkSeeAtList_" + data.Id + "' href='#'>Veja na lista</a>" +
                   "&nbsp;&nbsp;&nbsp;" +
                   "<a id='LnkSeeDetail_" + data.Id + "' href='" + cfg.VIEW_ESTATE_DETAIL + data.Id + "'>Detalhes</a>";

        return html;
    });

    var createListItemHTML = (function (data) {

        var html = "<a name='List_" + data.Id + "' id='List_" + data.Id + "'></ a>" +
                   "<p>" + data.OperationType + " - " + data.PropertyType + "<br />" +
                   "Valor: R$ " + data.PriceOrRentValue + "</p>" +
                   data.Address.Street + "<br />" +
                   data.Address.Neighborhood + " - " + data.Address.City + ", " + data.Address.State;

        return html;
    });

    var bindEstateToList = (function () {

        var itemLine = null;
        var idList = '#' + cfg.ESTATE_LIST_ID;
        var lenList = markersShowing.length;

        $(idList).children().remove('li');

        if (lenList == 0) {
            $('<li data-role=\"list-divider\"></li>')
                .append("Não foi encontrado nenhum imóvel com os filtros escolhidos.")
                .appendTo(idList);
        } else {
            $('<li data-role=\"list-divider\"></li>')
                .append("Imóveis")
                .appendTo(idList)
        }

        for (var i = 0; i < lenList; i++) {

            itemLine = markersShowing[i].dataSource;

            $('<li></li>')
                .append(createListItemHTML(itemLine))
                .bind('click', { lat: itemLine.PointLocation.Latitude, lng: itemLine.PointLocation.Longitude, markerCurrent: markersShowing[i] }, function (event) {

                    closeInfoWindow();

                    var latlng = new google.maps.LatLng(event.data.lat, event.data.lng);
                    map.setCenter(latlng);

                    google.maps.event.trigger(event.data.markerCurrent, 'click');

                    $.mobile.silentScroll();

                    return false;
                })
                .appendTo(idList);
        }

        $(idList).listview('refresh');
    });

    var clearMarkers = (function () {
        if (markersShowing) {
            for (i in markersShowing) {
                markersShowing[i].setMap(null);
            }
        }

        markersShowing = [];
    });

    var addInterestingPoints = (function () {
        consumer.doRequest(cfg.GET_INTERESTING_MARKERS, function (data) {
            var i = 0,
                markerListener;

            markerListener = function () {
                infoWindowDetail.setContent(this.html);
                infoWindowDetail.open(map, this);
            };

            for (; i < data.length; i++) {

                var point = new google.maps.LatLng(data[i].Latitude, data[i].Longitude);

                bounds.extend(point);

                var markerRent = new google.maps.Marker({
                    position: point,
                    map: map,
                    icon: imageIcons[data[i].MarkerType],
                    html: data[i].InfoContent
                });

                google.maps.event.addListener(markerRent, "click", markerListener);
            }

            map.fitBounds(bounds);
        },
            null
        );
    });

    var _searchCoordinates = function (address) {

        // Check to see if we already have a geocoded object. If not we create one
        if (!geocoder) {
            geocoder = new google.maps.Geocoder();
        }

        // Creating a GeocoderRequest object
        var geocoderRequest = {
            address: address
        };

        // Log geocoding use to respect limits used by service's provider
        $.ajax({
            type: "POST",
            url: cfg.LOG_GEOCODING_USE,
            dataType: "json",
            error: function (xhr, ajaxOptions, thrownError) { }
        });

        // Making the Geocode request to find location
        geocoder.geocode(geocoderRequest, function (results, status) {

            if (status !== google.maps.GeocoderStatus.OK) {
                jAlert(msg.LOCATION_NOT_FOUND, msg.INFORMATION_TITLE);
                return;
            }
            
            // Fires event alerting about location found
            $(window).trigger({
                type: INITIAL_POINT_LOCATED,
                initialPoint: results[0].geometry.location
            });

        });
    };

    var _allowGeocodingSearch = function (formId, txtId) {

        var form = document.getElementById(formId);
        var txt = document.getElementById(txtId);

        if (form == undefined || txt == undefined) {
            jAlert(msg.GEOCODING_CONTROL_FAIL);
            return;
        }

        // Catching the forms submit event
        form.onsubmit = function () {

            // Validations
            if ($.trim(txt.value) == "") {
                jAlert(msg.GEOCODING_INVALID_TEXT_SEARCH, msg.INFORMATION_TITLE, function () { txt.focus(); });
                return false;
            }

            // Checking if the google's geocoding  is released for use
            $.ajax({
                type: "POST",
                url: cfg.CHECK_GEOCODING_USE,
                dataType: "json",
                success: function (data) {
                    if (data) {
                        _searchCoordinates(txt.value);
                    } else {
                        jAlert(msg.GEOCODING_LIMIT_ACHIEVED, msg.INFORMATION_TITLE);
                    }
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    jAlert(xhr.status + "\n" + thrownError, msg.ERROR_TITLE);
                }
            });

            // Preventing the form from doing a page submit
            return false;
        };
    };

    var getFilterDistanceInMeters = (function () {

        var controlFilter = $("#" + cfg.SLIDER_DISTANCE_ID);

        if (controlFilter) {
            return parseInt(controlFilter.val());
        } else {
            return 1000;
        }
    });

    return {
        MAP_DONE_EVENT: MAP_DONE_EVENT,
        INITIAL_POINT_LOCATED: INITIAL_POINT_LOCATED,
        RENT_POINTS_ADDED_EVENT: RENT_POINTS_ADDED_EVENT,
        INTERESTING_POINTS_ADDED_EVENT: INTERESTING_POINTS_ADDED_EVENT,

        initializeMap: function () {
            initializeVariables();
            loadImages();
            createNewMap();
        },
        addInitialPointToMap: addInitialPointToMap,
        allowGeocodingSearch: _allowGeocodingSearch,
        addRentPoints: addRentPoints,
        addInterestingPoints: addInterestingPoints,
        getFilterDistanceInMeters: getFilterDistanceInMeters
    };

} (this.trilhaImovel.consumer,
   this.trilhaImovel.config,
   this.trilhaImovel.config.img,
   this.trilhaImovel.config.msg));



$(document).bind("mobileinit", function () {
    $.mobile.loadingMessage = "Processando";
    $.mobile.page.prototype.options.backBtnText = "Voltar";
});





